﻿//FENGTODO
using System;
using System.Collections.Generic;
//消息类型
using UnityEngine;

public enum MessengerMode
{
    //无接收者
    DONT_REQUIRE_LISTENER,
    //需要接受者
    REQUIRE_LISTENER,
}

#region MessengerInternal
static internal class MessengerInternal
{
    //监听存储器
    static public Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
    //
    static public readonly MessengerMode DEFAULT_MODE = MessengerMode.REQUIRE_LISTENER;

    //添加监听
    static public void OnListenerAdding(string eventType, Delegate listenerBeingAdded,bool isBro = true)
    {
        if (!eventTable.ContainsKey(eventType))
        {
            eventTable.Add(eventType, null);
        }

        Delegate d = eventTable[eventType];
        if (d != null && d.GetType() != listenerBeingAdded.GetType() && isBro)
        {
            throw new ListenerException(string.Format("添加监听事件: {0}.当前事件已经监听: {1} .事件监听添加为: {2}", eventType, d.GetType().Name, listenerBeingAdded.GetType().Name));
        }
    }
    //删除监听
    static public void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved)
    {
        if (eventTable.ContainsKey(eventType))
        {
            Delegate d = eventTable[eventType];

            if (d == null)
            {
                //没有找到监听器
                throw new ListenerException(string.Format("删除监听器： {0} 但是不存在监听器.", eventType));
            }
            else if (d.GetType() != listenerBeingRemoved.GetType())
            {
                //不是合适的监听器
                throw new ListenerException(string.Format("删除监听器 {0}. 需要删除的监听器 {1} 和该类型的监听器  {2} 不是同一个", eventType, d.GetType().Name, listenerBeingRemoved.GetType().Name));
            }
        }
        else
        {
          // throw new ListenerException(string.Format("删除 {0} 的监听器，但是并没有该监听者.", eventType));
        }
    }

    //
    static public void TryListenerRemove(string EventType, Delegate listenerremove)
    {
        
    }


    static public void OnListenerRemoved(string eventType)
    {
        if (eventTable[eventType] == null)
        {
            eventTable.Remove(eventType);
        }
    }


    static public void RemoveAllListener()
    {
        eventTable.Clear();
    }

    static public void OnBroadcasting(string eventType, MessengerMode mode)
    {
        if (mode == MessengerMode.REQUIRE_LISTENER && !eventTable.ContainsKey(eventType))
        {

            throw new MessengerInternal.BroadcastException(string.Format("发送消息 {0} 但是没有该消息的监听者。该消息需要监听者，若不需要请使用 MessengerMode.DONT_REQUIRE_LISTENER.", eventType));
        }
    }

    static public BroadcastException CreateBroadcastSignatureException(string eventType)
    {
        return new BroadcastException(string.Format("发送消息 {0} 但是这个消息已经存在不同的参数列表.", eventType));
    }


    #region BroadcastException ListenerException
    public class BroadcastException : Exception
    {
        public BroadcastException(string msg)
            : base(msg)
        {
        }
    }

    public class ListenerException : Exception
    {
        public ListenerException(string msg)
            : base(msg)
        {
        }
    }
    #endregion
}

#endregion


// 没有参数
static public class Messenger
{
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;

    static public void AddListener(string eventType, Callback handler,bool isclear=false)
    {
        if (isclear)
        {
            RemoveAllListener(eventType);
        }
        MessengerInternal.OnListenerAdding(eventType, handler);
        eventTable[eventType] = (Callback)eventTable[eventType] + handler;
    }

    static public void RemoveListener(string eventType, Callback handler)
    {
        MessengerInternal.OnListenerRemoving(eventType, handler);
        eventTable[eventType] = (Callback)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }



    static public void RemoveListener(string eventType, Delegate deDelegate)
    {
        MessengerInternal.OnListenerRemoving(eventType, deDelegate);
        //eventTable[eventType] = eventTable[eventType] - deDelegate;
        MessengerInternal.OnListenerRemoved(eventType);
    }
    

    static public void Broadcast(string eventType)
    {
        Broadcast(eventType, MessengerInternal.DEFAULT_MODE);
    }


    //删除所有指定类型的侦听器
    static public void RemoveAllListener(string eventType)
    {
        if (eventTable.ContainsKey(eventType))
        {
            eventTable.Remove(eventType);
        }
        
    }


    static public void Broadcast(string eventType, MessengerMode mode)
    {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d))
        {
            Callback callback = d as Callback;
            if (callback != null)
            {
                callback();
            }
            else
            {
                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
    }
}

// 一个参数
static public class Messenger<T>
{
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
    /// <summary>
    /// 监听消息 
    /// </summary>
    /// <param name="eventType">消息码</param>
    /// <param name="handler">回调函数</param>
    /// <param name="isclear">是否清空之前相同消息码的监听器   唯一监听   重复添加同一个监听器，只会注册最后添加一个</param>
    static public void AddListener(string eventType, Callback<T> handler,bool isclear=false)
    {
        if (isclear)
        {
            RemoveAllListener(eventType);
        }
        MessengerInternal.OnListenerAdding(eventType, handler);

        eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
    }

    static public void RemoveListener(string eventType, Callback<T> handler)
    {
        MessengerInternal.OnListenerRemoving(eventType, handler);
        if (!eventTable.ContainsKey(eventType))
        {
            return;
        }
        eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }




    //删除所有指定类型的侦听器
    static public void RemoveAllListener(string eventType)
    {
        if (eventTable.ContainsKey(eventType))
        {
            eventTable.Remove(eventType);
        }

    }

    //只可添加同一种监听者
    static public void AddListenerByOne(string eventType, Callback<T> handler)
    {
        RemoveAllListener(eventType);
        MessengerInternal.OnListenerAdding(eventType, handler,false);
        //避免重复
       // eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;
        eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
    }



    static public void Broadcast(string eventType, T arg1)
    {
        Broadcast(eventType, arg1, MessengerInternal.DEFAULT_MODE);
    }

    static public void Broadcast(string eventType, T arg1, MessengerMode mode)
    {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d))
        {
            Callback<T> callback = d as Callback<T>;
            if (callback != null)
            {
                callback(arg1);
            }
            else
            {
                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
    }
}


// 两个参数
static public class Messenger<T, U>
{
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
    /// <summary>
    /// 监听消息 
    /// </summary>
    /// <param name="eventType">消息码</param>
    /// <param name="handler">回调函数</param>
    /// <param name="isclear">是否清空之前相同消息码的监听器   唯一监听   重复添加同一个监听器，只会注册最后添加一个</param>
    static public void AddListener(string eventType, Callback<T, U> handler,bool isclear=false)
    {
        if (isclear)
        {
            RemoveAllListener(eventType);
        }
        MessengerInternal.OnListenerAdding(eventType, handler);

        eventTable[eventType] = (Callback<T, U>)eventTable[eventType] + handler;
    }

    static public void RemoveListener(string eventType, Callback<T, U> handler)
    {
        MessengerInternal.OnListenerRemoving(eventType, handler);
        eventTable[eventType] = (Callback<T, U>)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }



    static public void Broadcast(string eventType, T arg1, U arg2)
    {
        Broadcast(eventType, arg1, arg2, MessengerInternal.DEFAULT_MODE);
    }



    //删除所有指定类型的侦听器
    static public void RemoveAllListener(string eventType)
    {
        if (eventTable.ContainsKey(eventType))
        {
            eventTable.Remove(eventType);
        }

    }


    static public void Broadcast(string eventType, T arg1, U arg2, MessengerMode mode)
    {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d))
        {
            Callback<T, U> callback = d as Callback<T, U>;
            if (callback != null)
            {
                callback(arg1, arg2);

            }
            else
            {

                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
        else
        {
            
        }
    }
}


// 三个参数
static public class Messenger<T, U, V>
{
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
    /// <summary>
    /// 监听消息 
    /// </summary>
    /// <param name="eventType">消息码</param>
    /// <param name="handler">回调函数</param>
    /// <param name="isclear">是否清空之前相同消息码的监听器   唯一监听   重复添加同一个监听器，只会注册最后添加一个</param>
    static public void AddListener(string eventType, Callback<T, U, V> handler,bool isclear=false)
    {
        if (isclear)
        {
            RemoveAllListener(eventType);
        }
        MessengerInternal.OnListenerAdding(eventType, handler);

        eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] + handler;
    }

    static public void RemoveListener(string eventType, Callback<T, U, V> handler)
    {
        MessengerInternal.OnListenerRemoving(eventType, handler);
        eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }




    static public void Broadcast(string eventType, T arg1, U arg2, V arg3)
    {
        Broadcast(eventType, arg1, arg2, arg3, MessengerInternal.DEFAULT_MODE);
    }


    //删除所有指定类型的侦听器
    static public void RemoveAllListener(string eventType)
    {
        if (eventTable.ContainsKey(eventType))
        {
            eventTable.Remove(eventType);
        }

    }


    static public void Broadcast(string eventType, T arg1, U arg2, V arg3, MessengerMode mode)
    {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d))
        {
            Callback<T, U, V> callback = d as Callback<T, U, V>;
            if (callback != null)
            {
                callback(arg1, arg2, arg3);
            }
            else
            {
                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
    }
}




// 四个参数
static public class Messenger<T, U, V,Y>
{
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
    /// <summary>
    /// 监听消息 
    /// </summary>
    /// <param name="eventType">消息码</param>
    /// <param name="handler">回调函数</param>
    /// <param name="isclear">是否清空之前相同消息码的监听器   唯一监听   重复添加同一个监听器，只会注册最后添加一个</param>
    static public void AddListener(string eventType, Callback<T, U, V, Y> handler, bool isclear = false)
    {
        if (isclear)
        {
            RemoveAllListener(eventType);
        }
        MessengerInternal.OnListenerAdding(eventType, handler);

        eventTable[eventType] = (Callback<T, U, V, Y>)eventTable[eventType] + handler;
    }

    static public void RemoveListener(string eventType, Callback<T, U, V, Y> handler)
    {
        MessengerInternal.OnListenerRemoving(eventType, handler);
        eventTable[eventType] = (Callback<T, U, V, Y>)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }




    static public void Broadcast(string eventType, T arg1, U arg2, V arg3,Y arg4)
    {
        Broadcast(eventType, arg1, arg2, arg3, arg4, MessengerInternal.DEFAULT_MODE);
    }


    //删除所有指定类型的侦听器
    static public void RemoveAllListener(string eventType)
    {
        if (eventTable.ContainsKey(eventType))
        {
            eventTable.Remove(eventType);
        }

    }


    static public void Broadcast(string eventType, T arg1, U arg2, V arg3,Y arg4, MessengerMode mode)
    {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d))
        {
            Callback<T, U, V, Y> callback = d as Callback<T, U, V, Y>;
            if (callback != null)
            {
                callback(arg1, arg2, arg3,arg4);
            }
            else
            {
                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
    }
}